// Service Worker registration and management

const isLocalhost = Boolean(
  window.location.hostname === 'localhost' ||
  window.location.hostname === '[::1]' ||
  window.location.hostname.match(
    /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
  )
)

interface ServiceWorkerConfig {
  onSuccess?: (registration: ServiceWorkerRegistration) => void
  onUpdate?: (registration: ServiceWorkerRegistration) => void
  onOfflineReady?: () => void
}

export function registerSW(config?: ServiceWorkerConfig) {
  if ('serviceWorker' in navigator) {
    const baseUrl = (import.meta as any).env?.BASE_URL || '/'
    const publicUrl = new URL(baseUrl, window.location.href)
    if (publicUrl.origin !== window.location.origin) {
      return
    }

    window.addEventListener('load', () => {
      const swUrl = `${baseUrl}sw.js`

      if (isLocalhost) {
        checkValidServiceWorker(swUrl, config)
        navigator.serviceWorker.ready.then(() => {
          console.log(
            'This web app is being served cache-first by a service worker.'
          )
        })
      } else {
        registerValidSW(swUrl, config)
      }
    })
  }
}

async function registerValidSW(swUrl: string, config?: ServiceWorkerConfig) {
  try {
    const registration = await navigator.serviceWorker.register(swUrl)
    
    registration.onupdatefound = () => {
      const installingWorker = registration.installing
      if (installingWorker == null) {
        return
      }
      
      installingWorker.onstatechange = () => {
        if (installingWorker.state === 'installed') {
          if (navigator.serviceWorker.controller) {
            console.log(
              'New content is available and will be used when all tabs for this page are closed.'
            )
            if (config && config.onUpdate) {
              config.onUpdate(registration)
            }
          } else {
            console.log('Content is cached for offline use.')
            if (config && config.onSuccess) {
              config.onSuccess(registration)
            }
            if (config && config.onOfflineReady) {
              config.onOfflineReady()
            }
          }
        }
      }
    }
  } catch (error) {
    console.error('Error during service worker registration:', error)
  }
}

async function checkValidServiceWorker(swUrl: string, config?: ServiceWorkerConfig) {
  try {
    const response = await fetch(swUrl, {
      headers: { 'Service-Worker': 'script' },
    })
    
    const contentType = response.headers.get('content-type')
    if (
      response.status === 404 ||
      (contentType != null && contentType.indexOf('javascript') === -1)
    ) {
      const registration = await navigator.serviceWorker.ready
      await registration.unregister()
      window.location.reload()
    } else {
      registerValidSW(swUrl, config)
    }
  } catch {
    console.log('No internet connection found. App is running in offline mode.')
  }
}

export function unregister() {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.ready
      .then((registration) => {
        registration.unregister()
      })
      .catch((error) => {
        console.error(error.message)
      })
  }
}

// Utility functions for cache management
export async function clearCaches() {
  if ('caches' in window) {
    const cacheNames = await caches.keys()
    await Promise.all(
      cacheNames.map(cacheName => caches.delete(cacheName))
    )
    console.log('All caches cleared')
  }
}

export async function getCacheInfo() {
  if ('caches' in window) {
    const cacheNames = await caches.keys()
    const cacheInfo = await Promise.all(
      cacheNames.map(async (cacheName) => {
        const cache = await caches.open(cacheName)
        const keys = await cache.keys()
        return {
          name: cacheName,
          size: keys.length
        }
      })
    )
    return cacheInfo
  }
  return []
}

// Check if app is running offline
export function isOnline() {
  return navigator.onLine
}

// Listen for online/offline events
export function setupNetworkListeners(
  onOnline?: () => void,
  onOffline?: () => void
) {
  const handleOnline = () => {
    console.log('App is back online')
    onOnline?.()
  }

  const handleOffline = () => {
    console.log('App is offline')
    onOffline?.()
  }

  window.addEventListener('online', handleOnline)
  window.addEventListener('offline', handleOffline)

  return () => {
    window.removeEventListener('online', handleOnline)
    window.removeEventListener('offline', handleOffline)
  }
}

// Force service worker update
export async function updateServiceWorker() {
  if ('serviceWorker' in navigator) {
    const registration = await navigator.serviceWorker.ready
    await registration.update()
    console.log('Service worker update triggered')
  }
}
